<template>
  <article class="page page-img2pdf">
    <h4 class="text-center">图片转PDF</h4>
    <form class="form page-body">
      <fieldset>
        <legend>图片转PDF</legend>
        <div class="fieldset-content">
          <div class="form-item row">
            <div class="col col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">文档宽</div>
                <div class="row-flex-main"><input class="form-control" type="number" v-model.trim="docWidth" placeholder="请输入文档宽" min="0" /></div>
              </div>
            </div>
            <div class="col col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">文档高</div>
                <div class="row-flex-main"><input class="form-control" type="number" v-model.trim="docHeight" placeholder="请输入文档高" min="0" /></div>
              </div>
            </div>
          </div>
          <div class="form-item row">
            <div class="col col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">图片宽</div>
                <div class="row-flex-main"><input class="form-control" type="number" v-model.trim="imgWidth" placeholder="请输入图片宽，默认取图片自然宽度" min="0" /></div>
              </div>
            </div>
            <div class="col col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">图片高</div>
                <div class="row-flex-main"><input class="form-control" type="number" v-model.trim="imgHeight" placeholder="请输入图片高，默认取图片自然高度" min="0" /></div>
              </div>
            </div>
          </div>
          <div class="form-item row">
            <div class="col col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">图片起点X</div>
                <div class="row-flex-main"><input class="form-control" type="number" v-model.trim="imgX" placeholder="请输入图片X轴起点" /></div>
              </div>
            </div>
            <div class="col col-6">
              <div class="row-flex" align="center">
                <div class="row-flex-prefix">图片起点Y</div>
                <div class="row-flex-main"><input class="form-control" type="number" v-model.trim="imgY" placeholder="请输入图片Y轴起点" /></div>
              </div>
            </div>
          </div>
          <div class="row-flex" align="center">
            <div class="row-flex-prefix">质量(0-100)</div>
            <div class="row-flex-main"><input class="form-control" type="number" v-model.trim="quality" min="0" max="100" /></div>
          </div>
          <div class="row-flex" align="center">
            <div class="row-flex-prefix">MIMEType</div>
            <div class="row-flex-main"><input class="form-control" type="number" v-model.trim="mimeType" placeholder="请输入图片资源的媒体类型，默认取image/png" /></div>
          </div>
          <div class="row-flex" align="center">
            <div class="row-flex-prefix">保存位置</div>
            <div class="row-flex-main"><input class="form-control" type="text" v-model="toPath" /></div>
            <div class="row-flex-suffix"><x-button @click="setToPath">选择...</x-button></div>
          </div>
          <div class="row-flex" align="center">
            <div class="row-flex-prefix">资源来自</div>
            <div class="row-flex-main text-left">
              <label><input class="form-check-input" type="radio" value="web" v-model="fromType">网址</label>
              <label><input class="form-check-input" type="radio" value="local" v-model="fromType">本地图片</label>
            </div>
          </div>
          <div class="row-flex imgs-wrapper" align="center">
            <div class="row-flex-prefix"></div>
            <div class="row-flex-main">
              <div v-if="fromType === 'local'" class="img-list" @drop.prevent="drop" @dragover.prevent >
                <div class="img-item" v-for="(v,i) in localImagesList" :key="i">
                  <div class="img-item-text text-ellipsis" :title="v.name">{{v.name}}</div>
                  <div class="img-item-icon" @click="deleteImgItem(i)">
                    <i class="fa fa-close"></i>
                  </div>
                </div>
                <div v-show="localImagesList.length===0" class="nodata">将待处理图片拖动到此处</div>
              </div>
              <textarea v-else-if="fromType === 'web'" class="img-urls form-control" v-model="imageUrls" placeholder="请输入图片地址，用换行或空格分隔"></textarea>
            </div>
          </div>
          <div class="row-flex" align="center">
            <div class="row-flex-prefix"></div>
            <div class="row-flex-main">
              <div class="row">
                <div class="col col-6"><x-button block type="default" @click="resetData" :disabled="loadingCount > 0">重置</x-button></div>
                <div class="col col-6"><x-button block type="primary" @click="submitForm" :disabled="loadingCount > 0">执行操作</x-button></div>
              </div>
            </div>
          </div>
        </div>
      </fieldset>
      <div v-if="loadingCount > 0" class="mask">
        <x-loading></x-loading>
      </div>
    </form>
  </article>
</template>

<script>
const path = global.require('path')
const {remote} = global.require('electron')
const {dialog} = remote
const selfWindow= remote.getCurrentWindow()
let {jsPDF} = global.jspdf || {}

export default {
  name: 'img2pdf',
  data () {
    return {
      toPath: this.$sharedObject('desktopPath'),
      mmPerPx: 25.4 / 96 * 2.4,
      fromType: 'web',
      imgX: 0,
      imgY: 0,
      imgWidth: '',
      imgHeight: '',
      docWidth: '',
      docHeight: '',
      quality: 100,
      mimeType: '',
      imageUrls: '',
      webImagesList: [],
      localImagesList: [],
      loadingCount: 0
    }
  },
  methods: {
    // 重置
    resetData () {
      this.imgX = 0
      this.imgY = 0
      this.imgWidth = ''
      this.imgHeight = ''
      this.docWidth = ''
      this.docHeight = ''
      this.fromType = 'web'
      this.quality = 70
      this.mimeType = ''
      this.webImagesList = []
      this.localImagesList = []
    },
    // 设置保存位置
    setToPath () {
      let filePaths = dialog.showOpenDialogSync(selfWindow, {
        title: '选择目录',
        buttonLabel:'确定',
        defaultPath: this.$sharedObject('desktopPath'),
        properties: ['openDirectory']
      })
      if (filePaths instanceof Array && filePaths.length > 0) {
        this.toPath = filePaths[0]
      }
    },
    // 拖拽添加图片
    drop (e) {
      const fileList = e.dataTransfer.files
      if (!fileList) return
      // 文件类型不存在即认为是文件夹或特殊文件
      // 取文件后缀名，必须是图片文件
      let taskList = []
      let indexList = []
      for (let i = 0; i < fileList.length; i++) {
        const file = fileList[i]
        if (!file.type) {
          return this.$toast('不支持文件夹及特殊格式文件！')
        }
        if (!/.(gif|jpg|jpeg|png|gif|jpg|png)$/i.test(file.name)) {
          return this.$toast('请选择图片文件！')
        }
        taskList.push(this.$jstools.File2dataUrl(file))
        indexList.push(i)
      }
      Promise.all(taskList).then((urls) => {
        urls.forEach((v, i) => {
          let file = fileList[indexList[i]]
          this.localImagesList.push({
            name: file.name, src: v, path: file.path
          })
        })
      })
    },
    // 删除图片
    deleteImgItem (index) {
      this.localImagesList.splice(index, 1)
    },
    // 全部保存
    submitForm () {
      if (!this.toPath) {
        this.$toast('请设置图片保存位置')
        return
      }
      if (this.fromType === 'web') {
        let webImagesList = this.imageUrls.split(/\s/).filter(v => !!(v.trim()))
        this.webImagesList = webImagesList.map(v => {
          return {name: v, src: v, path: v}
        })
      }
      if (this[`${this.fromType}ImagesList`].length <= 0) {
        this.$toast('未找到可处理的图片')
        return
      }
      let taskList = []
      let doc = new jsPDF({unit: 'px'})
      this[`${this.fromType}ImagesList`].forEach(v => {
        taskList.push(this.$jstools.loadImage(v.src))
      })
      this.loadingCount++
      Promise.all(taskList).then((imgArr) => {
        imgArr = imgArr || []
        imgArr.forEach((img, i) => {
          let imgWidth = this.imgWidth || img.naturalWidth || img.clientWidth
          let imgHeight = this.imgHeight || img.naturalHeight || img.clientHeight
          let docWidth = this.docWidth || imgWidth * this.mmPerPx
          let docHeight = this.docHeight || imgHeight * this.mmPerPx
          let imgData = this.$jstools.img2dataUrl({
            img, width: imgWidth, height: imgHeight, quality: this.quality, mimeType: this.mimeType
          })
          let imgX = parseFloat(this.imgX) || 0
          let imgY = parseFloat(this.imgY) || 0
          if (i > 0) {doc.addPage()}
          doc.addImage(imgData, 'jpeg', imgX, imgY, docWidth, docHeight)
        })
        let rawData = doc.output('arraybuffer')
        let filePath = path.join(this.toPath, `${Date.now()}.pdf`)
        this.loadingCount++
        this.$sharedObject('jstoolsNode').writeFile(filePath, Buffer.from(rawData)).then(() => {
          this.$toast(`文件已保存到:${filePath}`)
        }).catch(err => {
          console.log(err)
          this.$toast('写入磁盘错误')
        }).finally(() => {
          this.loadingCount--
        })
      }).catch(err => {
        console.log(err)
        this.$toast('图片处理发生错误')
      }).finally(() => {
        this.loadingCount--
      })
    },
  }
}
</script>

<style scoped lang="less">
@import "~@/assets/css/_mixins.less";
@import "~@/assets/css/_color.less";
.row-flex {
  & + .row-flex {
    margin-top: .5em;
  }
  .row-flex-prefix {
    width: 6em;
    text-align: right;
  }
}
.form-item {
  margin-bottom: .5em;
}
label {
  & + label {
    margin-left: 1em;
  }
}
.page-img2pdf {
  display: flex;
  flex-direction: column;
  .page-body {
    height: 0;
    flex-grow: 1;
    position: relative;
    fieldset {
      height: 100%;
      .fieldset-content {
        height: calc(100% - 2em);
        display: flex;
        flex-direction: column;
        .imgs-wrapper {
          height: 0;
          flex-grow: 1;
          margin: 1em 0;
          .row-flex-main {
            height: 100%;
          }
        }
        .img-urls, .img-list {
          height: 100%;
          padding: .5em;
          border-radius: .5em;
          background-color: #fff;
          box-shadow: 0 0 .5em @bgGrey;
          overflow: hidden auto;
        }
        .img-urls {
          resize: none;
        }
        .img-list {
          position: relative;
          .img-item {
            height: 2em;
            display: flex;
            align-items: center;
            .img-item-text {
              width: 0;
              flex-grow: 1;
            }
            .img-item-icon {
              padding: 0 .5em;
              cursor: pointer;
            }
          }
        }
      }
    }
    .mask {
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      border-radius: 8px;
      background-color: rgba(255,255,255,.5);
      .flex-center;
    }
  }
}
</style>
